/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski                             *
 *   g.latarowski@gmail.com                                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// Qt
#include <QImageReader>

// gcommon
#include "gexception.h"

// gdialogs 
#include "gauthorizationdialog.h"

// gwidgets
#include "gconnectionwidget.h"
#include "gdockwidget.h"

// local
#include "window.h"
#include "eventsbaseconnection.h"


#define DEFAULT_DATABASE_FILENAME "tmp.sqlite3"

Q_IMPORT_PLUGIN( gjpeg2kjasper );



// ===========================================================================
//                                 Window
// ===========================================================================


// --------------------------- Window::Window() ------------------------------
Window::Window() : QMainWindow()
{
		// ui
	setupUi( this );

	message( tr( "Connect to camera." ) );

	// ====================================================
	// clear pointers 
	_pConnectionWidget    = NULL;

	// ====================================================
	// widgets
	
	_pConnectionWidget = new GConnectionWidget( this );
	if( toolBarConnection )
	{
		toolBarConnection->addWidget( _pConnectionWidget );
	}
		// dock dockEventImages
	if( dockEventImages )
	{
		this->addDockWidget( Qt::RightDockWidgetArea, dockEventImages );
	}
	
	// ====================================================
	// data base model
	
	_pModel = 0;

	// ====================================================
	// connections 

	connect( _pConnectionWidget, SIGNAL( connectToHost( const QString & ) ),
			 this, SLOT( connectToHost( const QString & ) ) );
	connect( _pConnectionWidget, SIGNAL( disconnectFromHost() ),
			 this, SLOT( disconnectFromHost() ) );
	
	connect( &_eventsClient, SIGNAL( disconnected() ),
			  this, SLOT( hostDisconnected() ) );
	connect( &_eventsClient, SIGNAL( authorizationFailed( const QString & ) ),
			  this, SLOT( authorizationFailed( const QString & ) ) );
	
	connect( dockEventImages, SIGNAL( visibleChanged( bool ) ),
			 actionEventImages, SLOT( setChecked( bool ) ) );
	connect( actionEventImages, SIGNAL( triggered( bool ) ),
			 dockEventImages, SLOT( setVisible( bool ) ) );

	connect( tableEvents, SIGNAL( clicked( const QModelIndex & ) ),
			 this, SLOT( itemClicked( const QModelIndex & ) ) );
	
	// ====================================================
	// restore settings
	
// 	QTimer::singleShot( 0, this, SLOT( restoreSettings() ) );
	restoreSettings();
}
// ---------------------------------------------------------------------------


// --------------------------- Window::~Window() -----------------------------
Window::~Window()
{
		// close connection to database 
    QSqlDatabase::removeDatabase( EVENTS_DATABASE_NAME );
}
// ---------------------------------------------------------------------------


// ------------------------- Window::saveSettings() --------------------------
void Window::saveSettings()
{
	QSettings settings;
	
		// write gui settings 
	settings.setValue( "geometry", this->saveGeometry() );
	settings.setValue( "state", this->saveState() );
	
		// save last _baseFileName 
	settings.setValue( "lastBaseFileName", QVariant( _baseFileName ) );
}
// ---------------------------------------------------------------------------


// ------------------------- Window::restoreSettings() -----------------------
void Window::restoreSettings()
{
	QSettings settings;
	 
		// restore GUI 
	this->restoreGeometry( settings.value( "geometry" ).toByteArray() );
	this->restoreState( settings.value( "state" ).toByteArray() );
	
		// restore last _baseFileName
	_baseFileName = settings.value( "lastBaseFileName", QString() ).toString();

	qDebug() << _baseFileName;
	openDatabase( _baseFileName );
}
// ---------------------------------------------------------------------------


// ------------------------- Window::closeEvent() ----------------------------
void Window::closeEvent( QCloseEvent * pEvent )
{
	saveSettings();
	
	QMainWindow::closeEvent( pEvent );   
}
// ---------------------------------------------------------------------------


// ------------------- Window::on_actionNew_triggered() ----------------------
void Window::on_actionNew_triggered()
{
	QPixmap pixmap( "multi.jpg" );  
// 	labelImage1->setPixmap( pixmap );
	qDebug( "setting" );
	imageViewer->setScaleLocked( true ); 
	imageViewer->addPixmap( pixmap );
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionOpen_triggered() --------------------
void Window::on_actionOpen_triggered()
{      
// 	QString fileName = QFileDialog::getOpenFileName( this,
// 			tr( "Open Configuration File" ),
// 			QDir::currentPath(),
// 			tr( "Autostop configuration files (*.xml)" ) );
// 	
// 	if ( fileName.isEmpty() ) return;
// 	
// 	QFile file( fileName );
// 	if ( !file.open( QFile::ReadOnly | QFile::Text ) )
// 	{
// 		QMessageBox::warning( this,
// 							  tr( "Adjuster" ),
// 							  tr( "Cannot read file %1:\n%2." )
// 									  .arg( fileName )
// 									  .arg( file.errorString() )
// 							);
// 		return;
// 	}
// 	if ( readConfigFile( &file ) )
// 	{
// 		message( tr( "Configuration file \"%1\" loaded" ).arg( fileName ) );
// 
// 			// configuration succesfully read, store opened fileName 
// 		_configFileName = fileName;
// 	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::on_actionSaveAs_triggered() ------------------
void Window::on_actionSaveAs_triggered()
{
// 	QString fileName = QFileDialog::getSaveFileName( this,
// 			tr( "Save Configuration File" ),
// 			QDir::currentPath(),
// 			tr( "Autostop configuration files (*.xml)" ) );
// 	
// 	if ( fileName.isEmpty() ) return;
// 
// 		// append extension if nessesarry
// 	if( !fileName.endsWith( ".xml" ) )
// 	{
// 		fileName.append( ".xml" );
// 	}
// 	
// 	QFile file( fileName );
// 	if ( !file.open( QFile::WriteOnly | QFile::Text ) )
// 	{
// 		QMessageBox::warning( this,
// 							  tr( "Adjuster" ),
// 							  tr( "Cannot write file %1:\n%2." )
// 									  .arg( fileName )
// 									  .arg( file.errorString() )
// 							);
// 		return;
// 	}
// 	
// 	if ( writeConfigFile( &file ) )
// 	{
// 		message( tr( "Configuration file \"%1\" saved" ).arg( fileName ) );
// 
// 			// configuration succesfully written, store saved fileName
// 		_configFileName = fileName;
// 	}
}
// ---------------------------------------------------------------------------


// --------------------- Window::connectToHost() -----------------------------
void Window::connectToHost( const QString & host )
{
		// if client was connect than disconnect
	if ( _eventsClient.isConnected() )
	{
		_eventsClient.disconnectFromHost();
	}

		// establish connection
	try
	{
		// before connection
			// set wait cursor icon
		setCursor( Qt::WaitCursor );
			// set disonnected
		if( _pConnectionWidget )
		{
			_pConnectionWidget->setDisconnected();
		}
			// show status that conencting
		message( tr( "Connecting to %1..." ).arg( host ) );

			// establish connection
		_eventsClient.connectToHost( host, EVENTS_PORT );

		// after connection is established
			// restore cursor
		setCursor( Qt::ArrowCursor );
		if( _eventsClient.isConnected() )
		{
				// set status
			message( tr( "Connection to %1 established." ).arg( host ) );

				// set connected
			if( _pConnectionWidget )
			{
				_pConnectionWidget->setConnected();
			}

			// process authentication
			GAuthorizationDialog authorizationDialog;
				// set host 
			authorizationDialog.setHost( host );
				// set last login
			authorizationDialog.setLogin( _lastLogin );
				// get userName & password string
			if( authorizationDialog.exec() )
			{
				_eventsClient.sendAuthorization( authorizationDialog.login(),
											     authorizationDialog.password()
											   );
				_lastLogin = authorizationDialog.login();
			}
			else
			{
					// break by user
				_eventsClient.disconnectFromHost();
					// set disonnected
				if( _pConnectionWidget )
				{
					_pConnectionWidget->setDisconnected();
				}
				return;
			}

				// connection estyablished
			connectedSetup();

		}
			// succes
		return;
	}
	catch( const GException& e )
	{
		message( tr("Connection error: %1" ).arg( e.getMessage() ) );
	}
		
	// defaultly - error or disconnected


		// show message
	message( tr( "Disconnected." ) );
		// set disonnected
	if( _pConnectionWidget )
	{
		_pConnectionWidget->setDisconnected();
	}
		// restore cursor
	setCursor( Qt::ArrowCursor );
	
		// disable buttons which requires valid network connection
	if( actionDownloadEvents )
	{
		actionDownloadEvents->setDisabled( true );
	}
}
// ---------------------------------------------------------------------------


// ----------------- Window::connectedSetup() --------------------------------
void Window::connectedSetup()
{
		// enable buttons which requires established network connection
	if( actionDownloadEvents )
	{
		actionDownloadEvents->setEnabled( true );
	}
}
// ---------------------------------------------------------------------------


// ----------------  Window::disconnectFromHost() ----------------------------
void Window::disconnectFromHost()
{
		// disconnec 
	if ( _eventsClient.isConnected() )
	{
		_eventsClient.disconnectFromHost();
	}
		// show message
	message( tr( "Disconnected." ) );
		// set disonnected
	if( _pConnectionWidget )
	{
		_pConnectionWidget->setDisconnected();
	}
		// restore cursor
	setCursor( Qt::ArrowCursor );
		// disable buttons which requires valid network connection
	if( actionDownloadEvents )
	{
		actionDownloadEvents->setDisabled( true );
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::hostDisconnected() ---------------------------
void Window::hostDisconnected()
{
	// set default as disconnected
	
		// restore cursor
	setCursor( Qt::ArrowCursor );
		// set disonnected
	if( _pConnectionWidget )
	{
		_pConnectionWidget->setDisconnected();
	}
	
		// show message
	message( tr( "Connection lost." ) );
		// disable buttons which requires valid network connection
	if( actionDownloadEvents )
	{
		actionDownloadEvents->setDisabled( true );
	}
}
// ---------------------------------------------------------------------------


// ------------------ Window::authorizationFailed() --------------------------
void Window::authorizationFailed( const QString & message )
{
	QMessageBox::warning( this,
						  tr( "Authorization failed" ),
						  message
						);
}
// ---------------------------------------------------------------------------


// ----------------------- Window::message() ---------------------------------
void Window::message( const QString & message, int timeout )
{
		// show message
	if( statusBar() )
	{
		statusBar()->showMessage( message, timeout );
	}
}
// ---------------------------------------------------------------------------


// ----------------- Window::on_actionDownloadEvents_triggered() -------------
void Window::on_actionDownloadEvents_triggered()
{
	if( !_eventsClient.isConnected() ) return;
	
	try
	{
		QList< Event > events = _eventsClient.events();
		insertEvents( events );
	}
	catch( const GException & e )
	{
		message( tr( "Camera error: %1" ).arg( e.getMessage() ) );
	}
}
// ---------------------------------------------------------------------------


// --------------------- Window::openDatabase() ------------------------------
void Window::openDatabase( const QString & baseFileName )
{
	_baseFileName = baseFileName;
    
        // create base 
	try
	{
		createEventBaseConnection( _baseFileName );
	}
	catch( const GException & e )
	{
		_baseFileName = QString( DEFAULT_DATABASE_FILENAME );
		try
		{
			createEventBaseConnection( _baseFileName );
		}
		catch( const GException & e )
		{
			QMessageBox::warning( this,
								  tr( "Mini Ticket Center" ),
								  tr( "Can not create database file!\n\n%1\n\n"
										  "Program will exit now." ).arg( e.getMessage() )
								);
			exit( 1 );
		}
	}
	qDebug() << _baseFileName;
    
        // create SQL model
	delete _pModel;
	_pModel = new QSqlTableModel;
    
        // read events description table 
	_pModel->setTable( "autostop_events" );
    _pModel->select();
	
		// add model to table 
	if( tableEvents )
	{
		tableEvents->setModel( _pModel );
		tableEvents->verticalHeader()->setVisible( false );
			// fit row heights
		tableEvents->resizeColumnsToContents( );
		tableEvents->resizeRowsToContents();
		if( tableEvents->horizontalHeader() )
		{
			tableEvents->horizontalHeader()->setHighlightSections( false );
			tableEvents->horizontalHeader()->setResizeMode( 0, QHeaderView::Interactive );
			tableEvents->horizontalHeader()->setResizeMode( 1, QHeaderView::Interactive );
			tableEvents->horizontalHeader()->setResizeMode( 2, QHeaderView::Interactive );
			tableEvents->horizontalHeader()->setResizeMode( 3, QHeaderView::Stretch );
		}
	} 
}
// ---------------------------------------------------------------------------


// ----------------------- Window::insertEvents() ----------------------------
void Window::insertEvents( const QList< Event > & events )
{
	foreach( Event event, events )
	{
			// insert next row
		int row = _pModel->rowCount();
		_pModel->insertRows( row, 1 );
		_pModel->setData( _pModel->index( row, 1 ), QVariant( event.type ) );
		_pModel->setData( _pModel->index( row, 2 ), QVariant( event.dateTime ) );
		_pModel->setData( _pModel->index( row, 3 ), QVariant( event.message ) );
		_pModel->submitAll();

			// insert first image 
		QSqlQuery query;
    	query.prepare( "INSERT INTO autostop_events_first_images ( image ) "
				"VALUES ( :image )" );
    	query.addBindValue( event.firstImage, QSql::In | QSql::Binary );
    	query.exec();
			// insert second image
		query.prepare( "INSERT INTO autostop_events_second_images ( image ) "
				"VALUES ( :image )" );
		query.addBindValue( event.secondImage, QSql::In | QSql::Binary );
		query.exec();
	}
}
// ---------------------------------------------------------------------------


// -------------------- Window::itemClicked() --------------------------------
void Window::itemClicked( const QModelIndex & index )
{
		// item id 
	int id = index.row() + 1;
		// extract images with id 
	QSqlQuery query;
		// first image 
	QString statement = QString( "SELECT image FROM autostop_events_first_images WHERE id = %1" ).arg( id );
	query.exec( statement );
		// first image found
// 	if( query.isSelect() )
// 	{
// 		query.first();
// 			// read image to buffer
// 		QByteArray firstImage = query.value( 0 ).toByteArray();
// 		QPixmap image;
// 		if( !image.loadFromData( firstImage, "j2c" ) )
// 		{
// 			qDebug("Invalid jpeg data, size: %d", firstImage.size() );
// 		}
// 			// schow image
// 		if( labelImage1 )
// 		{
// 			labelImage1->setPixmap( image );
// 		}
// 	}
// 
// 		// second image
// 	statement = QString( "SELECT image FROM autostop_events_second_images WHERE id = %1" ).arg( id );
// 	query.exec( statement );
// 		// first image found
// 	if( query.isSelect() )
// 	{
// 		query.first();
// 			// read image to buffer
// 		QByteArray secondImage = query.value( 0 ).toByteArray();
// 		QPixmap image;
// 		if( !image.loadFromData( secondImage, "j2c" ) )
// 		{
// 			qDebug("Invalid jpeg data, size: %d", secondImage.size() );
// 		}
// 			// schow image
// 		if( labelImage2 )
// 		{
// 			labelImage2->setPixmap( image );
// 		}
// 	}
}
// ---------------------------------------------------------------------------















// eof
